package com.oa.mail.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.mdp.core.entity.Tips;
import com.mdp.core.err.BizException;
import com.mdp.core.service.BaseService;
import com.mdp.safe.client.entity.User;
import com.mdp.safe.client.utils.LoginUtils;
import com.oa.mail.entity.*;
import com.oa.mail.mapper.MailEmailMapper;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.http.*;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;

/**
 * @author maimeng-mdp code-gen
 * @since 2023年10月9日
 */
@Service
public class MailEmailService extends BaseService<MailEmailMapper, MailEmail> {
    static Logger logger = LoggerFactory.getLogger(MailEmailService.class);

    /**
     * 自定义查询，支持多表关联
     *
     * @param page 分页条件
     * @param ew   一定要，并且必须加@Param("ew")注解
     * @param ext  如果xml中需要根据某些值进行特殊处理，可以通过这个进行传递，非必须，注解也可以不加
     * @return
     */
    public List<Map<String, Object>> selectListMapByWhere(IPage page, QueryWrapper ew, Map<String, Object> ext) {
        return baseMapper.selectListMapByWhere(page, ew, ext);
    }


    @Autowired
    MailEmailAddresseeService mailEmailAddresseeService;

    @Lazy
    @Autowired
    MailAccountService mailAccountService;

    JavaMailSenderImpl emailSender = new JavaMailSenderImpl();

    @Autowired
    RestTemplate restTemplate;

    @Autowired
    MailEmailAppendixService mailEmailAppendixService;

    public String mailProtocol = "smtp";
    public String mailDefaultEncoding = "utf-8";

    @Value("${mdp.api-gate:http://gate}")
    String apiGate = "";

    /**
     * 请在此类添加自定义函数
     */
    @Transactional
    public Integer save(MailEmailVo mailEmailVo) {

        Tips tips = new Tips("成功新增一条数据");

        mailEmailVo.setIsStar("0");
        mailEmailVo.setStatus("1");
        mailEmailVo.setSendTime(new Date());

        if (StringUtils.isEmpty(mailEmailVo.getId())) {
            mailEmailVo.setId(this.createKey("id"));
        } else {
            MailEmail mailEmailQuery = new MailEmail(mailEmailVo.getId());
            if (this.countByWhere(mailEmailQuery) > 0) {
                tips.setErrMsg("编号重复，请修改编号再提交");
                throw new BizException(tips);
            }
        }
        MailEmail mailEmail = new MailEmail();
        BeanUtils.copyProperties(mailEmailVo, mailEmail);
        int insert = this.insert(mailEmail);

        if (mailEmailVo.getType().equals("1") && mailEmailVo.getIsOuter().equals("0")) {
            MailEmail receivemailEmail = new MailEmail();
            mailEmailVo.setType("2");
            BeanUtils.copyProperties(mailEmailVo, receivemailEmail);
            receivemailEmail.setId("");
            saveMailEmail(receivemailEmail);
            mailEmailVo.setId(receivemailEmail.getId());
        }

        saveOtherMessage(mailEmailVo, tips);
        return insert;
    }

    //保存邮件基本信息
    public int saveMailEmail(MailEmail mailEmail, Tips tips) {
        if (StringUtils.isEmpty(mailEmail.getId())) {
            mailEmail.setId(this.createKey("id"));
        } else {
            MailEmail mailEmailQuery = new MailEmail(mailEmail.getId());
            if (this.countByWhere(mailEmailQuery) > 0) {
                tips.setErrMsg("编号重复，请修改编号再提交");
                throw new BizException(tips);
            }
        }
        return this.insert(mailEmail);
    }

    /**
     * 保存邮件的其它表信息
     *
     * @param mailEmailVo
     * @param tips
     */
    public void saveOtherMessage(MailEmailVo mailEmailVo, Tips tips) {
        //接收人列表
        ArrayList<String> toArr = new ArrayList<String>();
        //抄送人列表
        ArrayList<String> ccToArr = new ArrayList<String>();
        //密送人列表
        ArrayList<String> bccToArr = new ArrayList<String>();

        //保存收件人信息
        saveEmailToMessage(mailEmailVo, tips, toArr);
        //保存抄送人信息
        saveEmailCcMessage(mailEmailVo, tips, ccToArr);
        //保存密送人信息
        saveEmailBccMessage(mailEmailVo, tips, bccToArr);

        //判断是否保存为草搞
        if (mailEmailVo.getType().equals("0")) {
            saveEmailAppendixMessage(mailEmailVo, tips);
        } else {
            if (mailEmailVo.getIsOuter().equals("1")) {
                //发送邮件同时保存附件信息
                sendEmail(mailEmailVo, tips, toArr, ccToArr, bccToArr);
            } else {
                saveEmailAppendixMessage(mailEmailVo, tips);
            }
        }
    }

    public void sendEmail(MailEmailVo mailEmailVo, Tips tips, ArrayList<String> toArr, ArrayList<String> ccToArr, ArrayList<String> bccToArr) {

        String sendEmail = mailEmailVo.getSendEmail();
        MailAccount mailAccount = new MailAccount();
        mailAccount.setEmail(sendEmail);
        MailAccount selectOneObject = mailAccountService.selectOneObject(mailAccount);

        if (!StringUtils.isEmpty(selectOneObject)) {

            emailSender.setHost(selectOneObject.getSendServer()); //服务器名
            emailSender.setUsername(selectOneObject.getEmail());  //用户名
            emailSender.setPassword(selectOneObject.getPassword()); //密码
            emailSender.setPort(Integer.parseInt(selectOneObject.getSendPort())); //smtp端口
            emailSender.setProtocol(mailProtocol);
            emailSender.setDefaultEncoding(mailDefaultEncoding);

            Properties properties = new Properties();
            String sendIsSsl = selectOneObject.getSendIsSsl();
            boolean isSSL = true;
            if (sendIsSsl.equals("0")) {
                isSSL = false;
            }
            properties.put("mail.smtp.ssl.enable", isSSL);
            properties.put("mail." + mailProtocol + ".auth", true);
            emailSender.setJavaMailProperties(properties);

            try {
                MimeMessage mimeMessage = emailSender.createMimeMessage();
                MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "UTF-8");

                String[] strings = new String[toArr.size()];
                // To: 收件人（可以增加多个收件人、抄送、密送）
                mimeMessageHelper.setTo(toArr.toArray(strings));
                strings = new String[ccToArr.size()];
                mimeMessageHelper.setCc(ccToArr.toArray(strings));
                strings = new String[bccToArr.size()];
                mimeMessageHelper.setBcc(bccToArr.toArray(strings));

                String nick = "广州擎勤网络科技有限公司";
                if (selectOneObject.getIsUseNick().equals("1") && !StringUtils.isEmpty(selectOneObject.getNickName())) {
                    nick = selectOneObject.getNickName();
                }
                InternetAddress from = new InternetAddress(mailAccount.getEmail(), MimeUtility.encodeText(nick), "utf-8");
                // 设置发送人
                mimeMessageHelper.setFrom(from);
                // Subject: 邮件主题
                mimeMessageHelper.setSubject(mailEmailVo.getSubject());
                // Content: 邮件正文（可以使用html标签）
                mimeMessageHelper.setText(mailEmailVo.getContent(), true);

                //保存附件信息
                List<MailEmailAppendix> appendixList = mailEmailVo.getAppendixList();
                if (!appendixList.isEmpty()) {
                    for (MailEmailAppendix appendix : appendixList) {
                        if (StringUtils.isEmpty(appendix.getId())) {
                            appendix.setId(mailEmailAppendixService.createKey("id"));
                        } else {
                            MailEmailAppendix mailEmailAppendixQuery = new MailEmailAppendix(appendix.getId());
                            if (mailEmailAppendixService.countByWhere(mailEmailAppendixQuery) > 0) {
                                tips.setErrMsg("编号重复，请修改编号再提交");
                                throw new BizException(tips);
                            }
                        }
                        mailEmailAppendixService.insert(appendix);
                        InputStream execute = restTemplate.execute(apiGate + "/" + appendix.getAddr(), HttpMethod.GET, (clientHttpRequest) -> {
                            HttpHeaders httpHeaders = new HttpHeaders();
                            httpHeaders.add("content-type", "application/zip");
                            httpHeaders.add("content-disposition", "attachment; filename=export-single.zip");
                        }, (clientHttpResponse) -> {
                            InputStream inputStream = clientHttpResponse.getBody();
                            try {
                                mimeMessageHelper.addAttachment(appendix.getName(), new ByteArrayResource(StreamUtils.copyToByteArray(inputStream)));
                            } catch (MessagingException e) {
                                tips.setErrMsg(e.getMessage());
                                throw new BizException(tips);
                            }
                            return inputStream;
                        }, "");
                    }
                }
                emailSender.send(mimeMessage);

                //  第二种方式
                /*MimeMessage mimeMessage = new MimeMessage(emailSender.getSession());
                //// To: 收件人（可以增加多个收件人、抄送、密送）
                InternetAddress[] sendTo = InternetAddress.parse(to.get());
                mimeMessage.setRecipients(MimeMessage.RecipientType.TO, sendTo);
                // 设置发送人
                mimeMessage.setFrom(mailAccount.getEmail());
                // Subject: 邮件主题
                mimeMessage.setSubject(mailEmail.getSubject());
                // Content: 邮件正文（可以使用html标签）
                mimeMessage.setText(mailEmail.getContent());
                emailSender.send(mimeMessage);*/

                //  第一种方式
                /* MailMessage simpleMailMessage = new SimpleMailMessage();
                simpleMailMessage.setFrom(mailAccount.getEmail());
                simpleMailMessage.setSubject(mailEmail.getSubject());
                simpleMailMessage.setText(mailEmail.getContent());
                emailSender.send(simpleMailMessage);*/
            } catch (Exception e) {
                tips.setErrMsg(e.getMessage());
                throw new BizException(tips);
            }

        }
    }

    //保存附件信息
    public void saveEmailAppendixMessage(MailEmailVo mailEmailVo, Tips tips) {
        List<MailEmailAppendix> appendixList = mailEmailVo.getAppendixList();
        if (!appendixList.isEmpty()) {
            for (MailEmailAppendix appendix : appendixList) {
                if (StringUtils.isEmpty(appendix.getId())) {
                    appendix.setId(mailEmailAppendixService.createKey("id"));
                } else {
                    MailEmailAppendix mailEmailAppendixQuery = new MailEmailAppendix(appendix.getId());
                    if (mailEmailAppendixService.countByWhere(mailEmailAppendixQuery) > 0) {
                        tips.setErrMsg("编号重复，请修改编号再提交");
                        throw new BizException(tips);
                    }
                }
                mailEmailAppendixService.insert(appendix);
            }
        }
    }

    //保存密送人的信息
    public void saveEmailBccMessage(MailEmailVo mailEmailVo, Tips tips, ArrayList<String> bccToArr) {
        List<MailEmailAddressee> bccList = mailEmailVo.getBccList();
        if (!bccList.isEmpty()) {
            bccList.forEach((bcc) -> {
                bccToArr.add(bcc.getUserEmail());
                bcc.setEmailId(mailEmailVo.getId());

                if (StringUtils.isEmpty(bcc.getId())) {
                    bcc.setId(mailEmailAddresseeService.createKey("id"));
                } else {
                    MailEmailAddressee mailEmailBccQuery = new MailEmailAddressee(bcc.getId());
                    if (mailEmailAddresseeService.countByWhere(mailEmailBccQuery) > 0) {
                        tips.setErrMsg("编号重复，请修改编号再提交");
                        throw new BizException(tips);
                    }
                }
                mailEmailAddresseeService.insert(bcc);
            });
        }
    }

    //保存抄送人的信息
    public void saveEmailCcMessage(MailEmailVo mailEmailVo, Tips tips, ArrayList<String> ccToArr) {
        List<MailEmailAddressee> ccList = mailEmailVo.getCcList();
        if (!ccList.isEmpty()) {
            ccList.forEach((cc) -> {
                ccToArr.add(cc.getUserEmail());
                cc.setEmailId(mailEmailVo.getId());

                if (StringUtils.isEmpty(cc.getId())) {
                    cc.setId(mailEmailAddresseeService.createKey("id"));
                } else {
                    MailEmailAddressee mailEmailCcQuery = new MailEmailAddressee(cc.getId());
                    if (mailEmailAddresseeService.countByWhere(mailEmailCcQuery) > 0) {
                        tips.setErrMsg("编号重复，请修改编号再提交");
                        throw new BizException(tips);
                    }
                }
                mailEmailAddresseeService.insert(cc);
            });
        }
    }

    //保存接收人的信息
    public void saveEmailToMessage(MailEmailVo mailEmailVo, Tips tips, ArrayList<String> toArr) {
        List<MailEmailAddressee> addresseeList = mailEmailVo.getAddresseeList();
        if (!addresseeList.isEmpty()) {
            addresseeList.forEach((addressee) -> {
                toArr.add(addressee.getUserEmail());
                addressee.setEmailId(mailEmailVo.getId());

                if (StringUtils.isEmpty(addressee.getId())) {
                    addressee.setId(mailEmailAddresseeService.createKey("id"));
                } else {
                    MailEmailAddressee mailEmailAddresseeQuery = new MailEmailAddressee(addressee.getId());
                    if (mailEmailAddresseeService.countByWhere(mailEmailAddresseeQuery) > 0) {
                        tips.setErrMsg("编号重复，请修改编号再提交");
                        throw new BizException(tips);
                    }
                }
                mailEmailAddresseeService.insert(addressee);
            });
        }
    }

    @Transactional
    public Integer removeEmail(MailEmail mailEmail) {

        Integer delete = this.deleteByPk(mailEmail);

        if (!StringUtils.isEmpty(mailEmail.getId())) {
            removeOtherMessages(mailEmail);
        }
        return delete;
    }

    /**
     * 删除Mial的其它表的信息
     *
     * @param mailEmail
     */
    public void removeOtherMessages(MailEmail mailEmail) {
        MailEmailAddressee mailEmailAddressee = new MailEmailAddressee();
        mailEmailAddressee.setEmailId(mailEmail.getId());
        mailEmailAddresseeService.deleteByWhere(mailEmailAddressee);

       /* MailEmailBcc mailEmailBcc = new MailEmailBcc();
        mailEmailBcc.setEmailId(mailEmail.getId());
        mailEmailBccService.deleteByWhere(mailEmailBcc);

        MailEmailCc mailEmailCc = new MailEmailCc();
        mailEmailCc.setEmailId(mailEmail.getId());
        mailEmailCcService.deleteByWhere(mailEmailCc);*/

        MailEmailAppendix mailEmailAppendix = new MailEmailAppendix();
        mailEmailAppendix.setEmailId(mailEmail.getId());
        mailEmailAppendixService.deleteByWhere(mailEmailAppendix);
    }

    /**
     * 保存邮件基本信息
     *
     * @param mailEmail
     * @return
     */
    @Transactional
    public Integer saveMailEmail(MailEmail mailEmail) {
        Tips tips = new Tips();
        if (StringUtils.isEmpty(mailEmail.getId())) {
            mailEmail.setId(this.createKey("id"));
        } else {
            MailEmail mailEmailQuery = new MailEmail(mailEmail.getId());
            if (this.countByWhere(mailEmailQuery) > 0) {
                tips.setErrMsg("编号重复，请修改编号再提交");
                throw new BizException(tips);
            }
        }
        int insert = this.insert(mailEmail);
        return insert;
    }

    /**
     * 从邮件服务器收取邮件
     *
     * @param email
     * @return
     */
    @Transactional
    public List<MailEmail> receivetMail(String email) {

        Tips tips = new Tips("电子邮件帐号错误!");

        //String email = params.getEmail();
        MailAccount mailAccount = new MailAccount();
        mailAccount.setEmail(email);
        MailAccount selectOneObject = mailAccountService.selectOneObject(mailAccount);

        if (selectOneObject == null) {
            tips.setErrMsg("电子邮件帐号为空");
            throw new BizException(tips);
        }

        //获取session会话的方法
        Properties properties = System.getProperties();
        String protocol = "pop3";
        if (selectOneObject.getReceiveServerType().equals("1")) {
            protocol = "imap";
        }
        // todo sll 报错
//        if (selectOneObject.getReceiveIsSsl().equals("1")) {
//            //设置SSL连接、邮件环境
//            Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
//            final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
//            properties.setProperty("mail." + protocol + ".socketFactory.class", SSL_FACTORY);
//        }
        properties.put("mail.smtp.host", selectOneObject.getReceiveServer());
        properties.put("mail.smtp.auth", true);

        Session sessionMail = Session.getDefaultInstance(properties);

        Store store = null;
        Folder folder = null;
        int messageCount = 0;
        URLName urln = null;

        //进行用户邮箱连接
        try {
            urln = new URLName(protocol, selectOneObject.getReceiveServer(), Integer.parseInt(selectOneObject.getReceivePort()), null, selectOneObject.getEmail(), selectOneObject.getPassword());

            store = sessionMail.getStore(urln);
            store.connect();
            //获得邮箱内的邮件夹Folder对象，以"只读"打开
            folder = store.getFolder("INBOX"); //打开收件箱

            folder.open(Folder.READ_WRITE);

            //获得邮件夹Folder内的所有邮件个数
            messageCount = folder.getMessageCount(); // 获取所有邮件个数
            //获取新邮件处理
            logger.info("============>>邮件总数：" + messageCount);

            //查询数据库中的已有的数据
            int currntNum = 0;
//            int currntNum = messageCount - 11;
            MailEmail selectObject = new MailEmail();
            selectObject.setType("2");
            selectObject.setIsOuter("1");
            selectObject.setReceiveEmail(mailAccount.getEmail());
            List<MailEmail> newsByWheres = baseMapper.selectMailNewsByWhere(selectObject);
            if (!newsByWheres.isEmpty()) {
                MailEmail resultObject = newsByWheres.get(0);
                currntNum = resultObject.getCurrentNum();
            }

            if (messageCount > 0) {
                Message[] messages = folder.getMessages(currntNum + 1, messageCount);//读取最近的 currntNum 封邮件
                List<MailEmail> mailEmails = new ArrayList<>();

                for (int i = 0; i < messages.length; i++) {

                    MimeMessage mimeMessage = (MimeMessage) messages[i];

//                    System.out.println(mimeMessage.getFlags());
//                    System.out.println(mimeMessage.getMessageID());
//                    System.out.println(messages[i].getFlags().toString());
                    MailEmail newMailEmail = new MailEmail();
                    newMailEmail.setIsOuter("1");
                    newMailEmail.setIsRead("0");
                    newMailEmail.setIsStar("0");
                    newMailEmail.setStatus("1");
                    newMailEmail.setCurrentNum(currntNum + i + 1);
                    newMailEmail.setReceiveEmail(email);
                    newMailEmail.setAddressee(getMailTo(messages[i]));
                    newMailEmail.setCc(getMailCc(messages[i]));
                    newMailEmail.setBcc(getMailBcc(messages[i]));
                    newMailEmail.setSendEmail(getMailFrom(messages[i]));
                    User currentUserInfo = LoginUtils.getCurrentUserInfo();

                    newMailEmail.setBranchId(currentUserInfo.getBranchId());
                    StringBuffer bodytext = new StringBuffer();//存放邮件内容
                    newMailEmail.setContent(MimeUtility.decodeText(getMailContent((Part) messages[i], bodytext)));
                    newMailEmail.setType("2");
                    newMailEmail.setSubject(messages[i].getSubject());
                    newMailEmail.setSendTime(messages[i].getSentDate());

                    //保存邮件
                    saveMailEmail(newMailEmail);
                    mailEmails.add(newMailEmail);

                    if (isContainAttach((Part) messages[i])) {
                        saveAttachMent((Part) messages[i], newMailEmail.getId());
                    }
//                    System.out.println("=====================>>开始显示邮件内容<<=====================");
//                    System.out.println(messages[i].getSubject().trim());
//                    System.out.println(getMailFrom(messages[i]).trim());
//                    System.out.println(getMailTo(messages[i]).trim());
//                    System.out.println(getMailCc(messages[i]).trim());
//                    System.out.println(getMailBcc(messages[i]).trim());
//                    StringBuffer bodytext = new StringBuffer();//存放邮件内容
//                    System.out.println(getMailContent((Part)messages[i],bodytext).trim());
//                    System.out.println(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(messages[i].getSentDate()));
//                    System.out.println("是否有附件: " + (isContainAttach((Part)messages[i]) ? "有附件" : "无附件"));
//                    System.out.println("=====================>>结束显示邮件内容<<=====================");
                }
                return mailEmails;
            }


        } catch (Exception e) {
            tips.setErrMsg(e.getMessage());
            throw new BizException(tips);
        } finally {
            if (folder != null && folder.isOpen()) {
                try {
                    folder.close(true);
                } catch (MessagingException e) {
                    tips.setErrMsg(e.getMessage());
                    throw new BizException(tips);
                }
            }
            if (store.isConnected()) {
                try {
                    store.close();
                } catch (MessagingException e) {
                    tips.setErrMsg(e.getMessage());
                    throw new BizException(tips);
                }
            }
        }

        return null;
    }

    /**
     * 获取抄送人信息
     *
     * @param message
     * @return
     * @throws MessagingException
     */
    private String getMailCc(Message message) throws Exception {
        InternetAddress[] addresses = (InternetAddress[]) message.getRecipients(Message.RecipientType.CC);
        String cc = "";
        if (!StringUtils.isEmpty(addresses)) {
            for (int i = 0; i < addresses.length; i++) {
                cc += MimeUtility.decodeText(addresses[i].toString()) + ",";
            }
        }
        return cc;
    }

    /**
     * 获取密送人信息
     *
     * @param message
     * @return
     * @throws MessagingException
     */
    private String getMailBcc(Message message) throws Exception {
        InternetAddress[] addresses = (InternetAddress[]) message.getRecipients(Message.RecipientType.BCC);
        String bcc = "";
        if (!StringUtils.isEmpty(addresses)) {
            for (int i = 0; i < addresses.length; i++) {
                bcc += MimeUtility.decodeText(addresses[i].toString()) + ",";
            }
        }
        return bcc;
    }

    /**
     * 获取收件人的信息
     *
     * @param message
     * @return
     * @throws MessagingException
     */
    private String getMailTo(Message message) throws Exception {
        InternetAddress[] addresses = (InternetAddress[]) message.getRecipients(Message.RecipientType.TO);
        String to = "";
        if (!StringUtils.isEmpty(addresses)) {
            for (int i = 0; i < addresses.length; i++) {
                //to  +=  addresses[i].getAddress();
                to += MimeUtility.decodeText(addresses[i].toString()) + ",";

            }
        }
        return to;
    }

    /**
     * 获得发件人的地址
     *
     * @param message
     * @return 发件人的地址
     * @throws MessagingException
     */
    private String getMailFrom(Message message) throws Exception {
        InternetAddress[] addresses = (InternetAddress[]) message.getFrom();
        String form = "";
        if (!StringUtils.isEmpty(addresses)) {
            for (int i = 0; i < addresses.length; i++) {
//                form  +=  addresses[i].getAddress();
//                System.out.println(addresses[i].getPersonal());
//                System.out.println(MimeUtility.decodeText(addresses[i].toString()));
                form += MimeUtility.decodeText(addresses[i].toString()) + ",";
            }
        }
        return form;
    }

    /**
     * 获取邮件内容
     *
     * @param part：Part
     */
    private String getMailContent(Part part, StringBuffer bodytext) throws Exception {
//        System.out.println("text/plain" + part.isMimeType("text/plain"));
//        System.out.println("text/html" + part.isMimeType("text/html"));
//        System.out.println("multipart/*" + part.isMimeType("multipart/*"));
//        System.out.println("message/rfc822" + part.isMimeType("message/rfc822"));

        //判断邮件类型,不同类型操作不同
        if (part.isMimeType("text/plain")) {
            bodytext.append((String) part.getContent());
        } else if (part.isMimeType("text/html")) {
            bodytext.append((String) part.getContent());
        } else if (part.isMimeType("multipart/*")) {
            Multipart multipart = (Multipart) part.getContent();
            int counts = multipart.getCount();
            for (int i = 0; i < counts; i++) {
                getMailContent(multipart.getBodyPart(i), bodytext);
            }
        } else if (part.isMimeType("message/rfc822")) {
            getMailContent((Part) part.getContent(), bodytext);
        } else {
        }
        return bodytext.toString();
    }

    /**
     * 判断此邮件是否包含附件
     *
     * @param part
     * @return 否包含附件
     * @throws Exception
     */
    private boolean isContainAttach(Part part) throws Exception {
        boolean attachflag = false;
        if (part.isMimeType("multipart/*")) {
            Multipart mp = (Multipart) part.getContent();
            for (int i = 0; i < mp.getCount(); i++) {
                BodyPart mpart = mp.getBodyPart(i);
                String disposition = mpart.getDisposition();
                if (!StringUtils.isEmpty(disposition) && ((disposition.equals(Part.ATTACHMENT)) || (disposition.equals(Part.INLINE)))) {
                    attachflag = true;
                } else if (mpart.isMimeType("multipart/*")) {
                    attachflag = isContainAttach(((Part) mpart));
                } else {
                    String contentType = mpart.getContentType();
                    if (contentType.toLowerCase().indexOf("application") != -1) {
                        attachflag = true;
                    }
                    if (contentType.toLowerCase().indexOf("name") != -1) {
                        attachflag = true;
                    }
                }
            }
        } else if (part.isMimeType("message/rfc822")) {
            attachflag = isContainAttach((Part) part.getContent());
        }
        return attachflag;
    }

    /**
     * 保存附件
     *
     * @param part：Part
     * @param id：id
     */
    private void saveAttachMent(Part part, String id) throws IOException, MessagingException {
        Tips tips = new Tips();
        String fileName = "";
        //保存附件到服务器本地
        if (part.isMimeType("multipart/*")) {
            Multipart mp = (Multipart) part.getContent();
            for (int i = 0; i < mp.getCount(); i++) {
                BodyPart mpart = mp.getBodyPart(i);
                String disposition = mpart.getDisposition();
                if ((disposition != null) && ((disposition.equals(Part.ATTACHMENT)) || (disposition.equals(Part.INLINE)))) {
                    fileName = mpart.getFileName();
                    if (fileName != null) {
                        fileName = MimeUtility.decodeText(fileName);

                        InputStream inputStream = null;
                        OutputStream os = null;
                        try {
                            inputStream = mpart.getInputStream();
                            FileItemFactory factory = new DiskFileItemFactory(16, null);
                            FileItem item = factory.createItem(fileName, "text/plain", true, fileName);
                            int bytesRead = 0;
                            os = item.getOutputStream();
                            byte[] buffer = new byte[8192];
                            while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
                                os.write(buffer, 0, bytesRead);
                            }
                            MultipartFile multipartFile = new CommonsMultipartFile(item);
                            Resource resource = multipartFile.getResource();

                            //设置请求头
                            HttpHeaders headers = new HttpHeaders();
                            MediaType type = MediaType.parseMediaType("multipart/form-data");
                            headers.setContentType(type);

                            User currentUserInfo = LoginUtils.getCurrentUserInfo();

                            //设置请求体，注意是LinkedMultiValueMap
                            MultiValueMap<String, Object> form = new LinkedMultiValueMap<>();
//                            Resource resource = new InputStreamResource(inputStream);
                            form.add("file", resource);
                            form.add("remark", "");
                            form.add("bizId", "bizz");
                            form.add("archiveId", id);
                            form.add("categoryId", "");
                            form.add("deptid", "");
                            form.add("branchId", currentUserInfo.getBranchId());

                            //用HttpEntity封装整个请求报文
                            HttpEntity<MultiValueMap<String, Object>> files = new HttpEntity<>(form, headers);

                            String uploadUrl = apiGate + "/arc/arc/mdp/arc/file/upload";
                            ResponseEntity<Map> exchange = restTemplate.exchange(uploadUrl, HttpMethod.POST, files, Map.class);
                            System.out.println(exchange);
                            if (exchange.getStatusCodeValue() == 200) {
                                System.out.println(exchange.getBody());
                                Map body = exchange.getBody();
                                System.out.println(body.get("data"));
                                Map<String, String> data = (Map<String, String>) body.get("data");
                                MailEmailAppendix mailEmailAppendix = new MailEmailAppendix();
                                mailEmailAppendix.setEmailId(id);
                                mailEmailAppendix.setId(data.get("id"));
                                mailEmailAppendix.setAddr(data.get("url"));
                                mailEmailAppendix.setRemark("");
                                mailEmailAppendix.setType(data.get("fileSuffix"));
                                mailEmailAppendix.setName(data.get("name"));
                                mailEmailAppendixService.insert(mailEmailAppendix);
                            }

                        } catch (Exception e) {
                            tips.setErrMsg(e.getMessage());
                            throw new BizException(tips);
                        } finally {
                            os.close();
                            inputStream.close();
                        }
                    }
                } else if (mpart.isMimeType("multipart/*")) {
                    saveAttachMent(mpart, id);
                } else {
                    fileName = mpart.getFileName();
                    if (fileName != null) {
                        fileName = MimeUtility.decodeText(fileName);

                    }
                }
            }
        } else if (part.isMimeType("message/rfc822")) {
            saveAttachMent((Part) part.getContent(), id);
        }
    }


    /**
     * 获得邮件主题
     *
     * @param message：Message
     * @return 邮件主题
     */
    private String getSubject(Message message) throws Exception {
        String subject = "";
        if (((MimeMessage) message).getSubject() != null) {
            subject = MimeUtility.decodeText(((MimeMessage) message).getSubject());// 将邮件主题解码
        }
        return subject;
    }

    /**
     * 获取收取邮件的Session
     *
     * @param mailAccount
     * @param protocol
     * @return
     */
    private Session getSesssionMail(MailAccount mailAccount, String protocol) {
        Properties properties = System.getProperties();
        // todo sll 报错
//        if (mailAccount.getReceiveIsSsl().equals("1")) {
//            //设置SSL连接、邮件环境
//            Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
//            final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
//            properties.setProperty("mail." + protocol + ".socketFactory.fallback", "false");
//            properties.setProperty("mail." + protocol + ".socketFactory.class", SSL_FACTORY);
//        }
        properties.put("mail.smtp.host", mailAccount.getReceiveServer());
        properties.put("mail.smtp.auth", true);

        return Session.getDefaultInstance(properties);
    }


    /**
     * 检查账号新邮件数
     *
     * @param mailAccount
     * @return
     */
    public Integer checkNewEmail(MailAccount mailAccount) {
        Tips tips = new Tips();
        String protocol = "pop3";
        if (mailAccount.getReceiveServerType().equals("1")) {
            protocol = "imap";
        }
        //获取session会话的方法
        Session sessionMail = getSesssionMail(mailAccount, protocol);

        Store store = null;
        Folder folder = null;
        URLName urln = null;

        //查询数据库中的已有的数据
        int currntNum = 0;
        MailEmail mailEmail = new MailEmail();
        mailEmail.setType("2");
        mailEmail.setIsOuter("1");
        mailEmail.setReceiveEmail(mailAccount.getEmail());
        List<MailEmail> newsByWheres = baseMapper.selectMailNewsByWhere(mailEmail);
        if (!newsByWheres.isEmpty()) {
            MailEmail resultObject = newsByWheres.get(0);
            currntNum = resultObject.getCurrentNum();
        }

        //进行用户邮箱连接
        try {
            urln = new URLName(protocol, mailAccount.getReceiveServer(), Integer.parseInt(mailAccount.getReceivePort()), null, mailAccount.getEmail(), mailAccount.getPassword());
            store = sessionMail.getStore(urln);
            store.connect();
            //获得邮箱内的邮件夹Folder对象，以"只读"打开
            folder = store.getFolder("INBOX"); //打开收件箱
            folder.open(Folder.READ_WRITE);  //设置只读
            //邮件数
//            folder.getPermanentFlags()
            int messageCount = folder.getMessageCount();

            return messageCount - currntNum;
        } catch (Exception e) {
            tips.setErrMsg(e.getMessage());
            throw new BizException(tips);
        } finally {
            if (folder != null && folder.isOpen()) {
                try {
                    folder.close(true);
                } catch (MessagingException e) {
                    e.printStackTrace();
                }
            }
            if (store.isConnected()) {
                try {
                    store.close();
                } catch (MessagingException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 查询一个email的全部信息
     *
     * @param mailEmail
     * @return
     */
    public MailEmailVo getMailEmail(Map<String, Object> mailEmail) {

        MailEmailVo mailEmailVo = new MailEmailVo();

        String id = (String) mailEmail.get("id");
        MailEmail param = new MailEmail();
        param.setId(id);
        MailEmail selectOneObject = this.selectOneObject(param);

        if (selectOneObject != null) {
            BeanUtils.copyProperties(selectOneObject, mailEmailVo);

            MailEmailAddressee mailEmailAddressee = new MailEmailAddressee();
            mailEmailAddressee.setEmailId(selectOneObject.getId());
            mailEmailAddressee.setReceiveType("0");
            List<MailEmailAddressee> mailEmailAddressees = mailEmailAddresseeService.selectListByWhere(mailEmailAddressee);
            mailEmailVo.setAddresseeList(mailEmailAddressees);

            MailEmailAddressee mailEmailCc = new MailEmailAddressee();
            mailEmailCc.setEmailId(selectOneObject.getId());
            mailEmailCc.setReceiveType("1");
            List<MailEmailAddressee> mailEmailCcs = mailEmailAddresseeService.selectListByWhere(mailEmailCc);
            mailEmailVo.setCcList(mailEmailCcs);

            MailEmailAddressee mailEmailBcc = new MailEmailAddressee();
            mailEmailBcc.setEmailId(selectOneObject.getId());
            mailEmailBcc.setReceiveType("2");
            List<MailEmailAddressee> mailEmailBccs = mailEmailAddresseeService.selectListByWhere(mailEmailBcc);
            mailEmailVo.setBccList(mailEmailBccs);

            MailEmailAppendix mailEmailAppendix = new MailEmailAppendix();
            mailEmailAppendix.setEmailId(selectOneObject.getId());
            List<MailEmailAppendix> mailEmailAppendices = mailEmailAppendixService.selectListByWhere(mailEmailAppendix);
            mailEmailVo.setAppendixList(mailEmailAppendices);
        }

        return mailEmailVo;
    }

    @Transactional
    public Integer editMailEmail(MailEmailVo mailEmailVo) {

        Tips tips = new Tips();
        mailEmailVo.setSendTime(new Date());

        if (StringUtils.isEmpty(mailEmailVo.getId())) {
            tips.setErrMsg("系统错误,id没有!!!");
            throw new BizException(tips);
        }

        MailEmail mailEmail = new MailEmail();
        BeanUtils.copyProperties(mailEmailVo, mailEmail);
        int i = this.updateByPk(mailEmail);

        if (mailEmailVo.getType().equals("1") && mailEmailVo.getIsOuter().equals("0")) {
            MailEmail receivemailEmail = new MailEmail();
            mailEmailVo.setType("2");
            mailEmailVo.setIsStar("0");
            BeanUtils.copyProperties(mailEmailVo, receivemailEmail);
            receivemailEmail.setId("");
            saveMailEmail(receivemailEmail);
            mailEmailVo.setId(receivemailEmail.getId());
        }

        //删除其它表的信息
        removeOtherMessages(mailEmail);

        //保存其它表的信息
        saveOtherMessage(mailEmailVo, tips);
        return i;
    }

    public Integer setStarMail(MailEmail mailEmail) {
        Integer update = this.updateByPk(mailEmail);
        return update;
    }

    public List<Map<String, Object>> selectListMapByWhereByStar(Map<String, Object> mailEmail) {
        return baseMapper.selectListMapByWhereByStar(mailEmail);
    }

    public List<Map<String, Object>> selectListMapByWhereByMoreParams(Map<String, Object> mailEmail) {
        return baseMapper.selectListMapByWhereByMoreParams(mailEmail);
    }
}

